package com.mew.chess.core.game.pokdeng.game;

import cn.hutool.core.util.RandomUtil;
import com.mew.chess.core.game.pokdeng.game.common.PokDengCardType;
import com.mew.chess.core.game.pokdeng.game.common.PokDengConstantValue;
import com.mew.chess.core.game.pokdeng.game.common.PokDengLinkType;
import com.mew.chess.core.game.pokdeng.game.core.CardUtil;
import com.mew.chess.core.game.pokdeng.game.core.RobotUtil;
import com.mew.chess.core.game.pokdeng.game.core.TableUtil;
import com.mew.chess.core.game.pokdeng.game.message.UserMessage;
import com.mew.chess.core.game.pokdeng.game.task.*;
import com.mew.common.config.SpringContextBean;
import com.mew.common.enm.UserType;
import com.zebra.common.concurrent.ZebraScheduler;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;

import java.util.Iterator;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;


/**
 * @author dylin
 */
@Data
@ToString(of = {"tableId"})
@NoArgsConstructor
@Slf4j
public class PokDengScheduleManager {
    private AtomicBoolean flag = new AtomicBoolean(false);

    private int roomId;
    private int tableId;
    private Iterator<PokDengSeatManager> seatIterator;

    private ZebraScheduler zebraScheduler;
    private ExecutorService executorService;

    private ScheduledFuture<?> scheduledFuture;

    private PokDengStartBetTask startBetTask;
    private PokDengDealCardTask dealCardTask;
    private PokDengAskCardTask askCardTask;
    private PokDengMiCardTask miCardTask;
    private PokDengOpenCardTask openCardTask;
    private PokDengPaymentTask paymentTask;

    public PokDengScheduleManager(int roomId,int tableId, ZebraScheduler zebraScheduler, ExecutorService executorService){
        this.roomId = roomId;
        this.tableId = tableId;
        this.zebraScheduler = zebraScheduler;
        this.executorService = executorService;
    }

    private void initializeTask(){

        if (null == startBetTask){
            startBetTask = SpringContextBean.getBean(PokDengStartBetTask.class);
        }
        if (null == dealCardTask){
            dealCardTask = SpringContextBean.getBean(PokDengDealCardTask.class);
        }
        if (null == askCardTask){
            askCardTask = SpringContextBean.getBean(PokDengAskCardTask.class);
        }
        if (null == miCardTask){
            miCardTask = SpringContextBean.getBean(PokDengMiCardTask.class);
        }
        if (null == openCardTask){
            openCardTask = SpringContextBean.getBean(PokDengOpenCardTask.class);
        }

        if (null == paymentTask){
            paymentTask = SpringContextBean.getBean(PokDengPaymentTask.class);
        }

    }

    public void start(){
        if(flag.compareAndSet(false, true)){
            initializeTask();
            prepareStartTimer();
        }
    }

    public void stop(){
        ZebraScheduler.cancelScheduled(scheduledFuture);
        flag.getAndSet(false);
    }

    public void skipBet(){
        ZebraScheduler.cancelScheduled(scheduledFuture);
        doDealCard();
    }

    /**
     * 准备阶段
     */
    private void prepareStartTimer(){

        PokDengTableManager tableManager=PokDengGameManager.getInstance().getController(roomId).getTableManager(tableId);
        tableManager.changeLink(PokDengLinkType.Prepare.code(), PokDengConstantValue.PREPARE_TIME);
        scheduledFuture = zebraScheduler.schedule((this::doStartBet), PokDengConstantValue.PREPARE_TIME, TimeUnit.MILLISECONDS, executorService);
    }
    /**
     *压注阶段
     */
    private void doStartBet(){
        if (!startBetTask.startBet(roomId,tableId)){
            return;
        }
        scheduledFuture = zebraScheduler.schedule((this::doDealCard), PokDengConstantValue.START_BET_TIME, TimeUnit.MILLISECONDS, executorService);
        RobotUtil.robotBet(roomId,tableId);
    }
    /**
     * 发牌阶段
     */
    private void doDealCard(){
        //如果庄家是天牌 跳过要牌阶段  直接开牌
        if(dealCardTask.dealCard(roomId,tableId)){
            scheduledFuture = zebraScheduler.schedule((this::doOpenCard), PokDengConstantValue.DEAL_CARD_TIME, TimeUnit.MILLISECONDS, executorService);
        }else{
            scheduledFuture = zebraScheduler.schedule((this::doAskCard), PokDengConstantValue.DEAL_CARD_TIME, TimeUnit.MILLISECONDS, executorService);
        }

    }

    /**
     * 轮询要牌阶段
     */
    public void doAskCard(){
        if(seatIterator==null){
            seatIterator=TableUtil.buildSeatIterator(roomId,tableId);
        }
        ZebraScheduler.cancelScheduled(scheduledFuture);
        //座位轮询  轮询完毕后询问庄家要牌
        if(seatIterator.hasNext()){
            PokDengSeatManager seat = seatIterator.next();
            UserMessage user=seat.getUser();
            //跳过阶段的判断条件： 没牌 无需补牌
            if(user==null||user.getBet()==0||user.getCardType()== PokDengCardType.Major.code()){
                doAskCard();
            }else{
                //需要系统补牌
                if(CardUtil.isNeedSysDeal(user.getCards())){
                    System.out.println(user.getNickname()+"自动补牌");
                    int card = TableUtil.sysAskCard(roomId, tableId, seat.getSeatNo());
                    if(card != -1){
                        TableUtil.sendAskCardMessage(PokDengGameManager.getInstance().getController(roomId).getTableManager(tableId),seat);
                    }
                    doAskCard();
                }else{
                    askCardTask.askCard(roomId,tableId,user.getSeatNo());
                    if(user.getUserType()== UserType.Robot.code()){
                        try {
                            TimeUnit.MILLISECONDS.sleep(RandomUtil.randomLong(1000,3000));
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        int card = TableUtil.bankerOrRobotAskCard(roomId, tableId, seat.getSeatNo());
                        if(card != -1){
                            TableUtil.sendAskCardMessage(PokDengGameManager.getInstance().getController(roomId).getTableManager(tableId),seat);
                        }
                        doAskCard();
                    }else{
                        scheduledFuture = zebraScheduler.schedule((this::doAskCard), PokDengConstantValue.ASK_CARD_TIME, TimeUnit.MILLISECONDS, executorService);
                    }
                }
            }
        }else{
            seatIterator=null;
            doBankerAskCard(askCardTask.hasControl(roomId));
        }
    }

    /**
     * 庄家要牌阶段
     */
    private void doBankerAskCard(boolean control){
        int time = 0;
        PokDengTableManager tableManager=PokDengGameManager.getInstance().getController(roomId).getTableManager(tableId);
        UserMessage banker=tableManager.getBanker().getUser();
        //判断庄家是否需要补牌
        if(banker.getCardType()!=PokDengCardType.Major.code()) {
            if(CardUtil.isNeedSysDeal(banker.getCards())){
                int card = TableUtil.sysAskCard(roomId,tableId,tableManager.getBanker().getSeatNo());
                if(control){
                    log.info("----- POKDENG control --------------");
                    while(TableUtil.computeBankerWin(tableManager) < 0 && time <50){
                        TableUtil.resetBankerAsk(tableManager);
                        card = TableUtil.sysAskCard(roomId,tableId,tableManager.getBanker().getSeatNo());
                        time++;
                    }
                }
                if(card != -1){
                    TableUtil.sendAskCardMessage(tableManager,tableManager.getBanker());
                }
                doMiCard();
            }else {
                askCardTask.askCard(roomId, tableId, tableManager.getBanker().getSeatNo());
                int card = TableUtil.bankerOrRobotAskCard(roomId, tableId,tableManager.getBanker().getSeatNo());
                if(control){
                    log.info("----- POKDENG control --------------");
                    while(TableUtil.computeBankerWin(tableManager) < 0 && time <50){
                        TableUtil.resetBankerAsk(tableManager);
                        card = TableUtil.bankerOrRobotAskCard(roomId, tableId,tableManager.getBanker().getSeatNo());
                        time++;
                    }
                }
                if(card != -1){
                    TableUtil.sendAskCardMessage(tableManager,tableManager.getBanker());
                }
                try {
                    TimeUnit.MILLISECONDS.sleep(RandomUtil.randomLong(1000,3000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                doMiCard();
            }
        }else{
            doMiCard();
        }
    }
    private void doMiCard(){
        miCardTask.miCard(roomId,tableId);
        scheduledFuture = zebraScheduler.schedule((this::doOpenCard), PokDengConstantValue.MI_CARD_TIME, TimeUnit.MILLISECONDS, executorService);
    }
    /**
     * 开牌阶段
     */
    private void doOpenCard(){
        openCardTask.openCard(roomId,tableId);
        scheduledFuture = zebraScheduler.schedule((this::doPayment), PokDengConstantValue.OPEN_CARD_TIME, TimeUnit.MILLISECONDS, executorService);
    }
    /**
     * 赔付阶段
     */
    private void doPayment(){
        paymentTask.payment(roomId,tableId);
        scheduledFuture = zebraScheduler.schedule((this::doStartBet), PokDengConstantValue.PAYMENT_TIME, TimeUnit.MILLISECONDS, executorService);
    }
}
